package handlers

import (
	"database/sql"
	"log"

	_ "github.com/go-sql-driver/mysql"
)

var db *sql.DB

// InitDB 初始化数据库连接
func InitDB(dsn string) {
	var err error
	db, err = sql.Open("mysql", dsn)
	if err != nil {
		log.Fatalf("Error opening database: %v", err)
	}

	// 检查数据库连接
	if err = db.Ping(); err != nil {
		log.Fatalf("Database is not reachable: %v", err)
	}

	log.Println("Database connection established successfully")
}

// GetDB 返回数据库连接
func GetDB() *sql.DB {
	return db
}

// ExecuteQuery 执行查询并返回结果切片
func ExecuteQuery(query string, args ...interface{}) ([]map[string]interface{}, error) {
	rows, err := db.Query(query, args...)
	if err != nil {
		return nil, logError("query execution failed", err)
	}
	defer rows.Close()

	// 获取列名
	columns, err := rows.Columns()
	if err != nil {
		return nil, logError("fetching columns failed", err)
	}

	// 创建一个切片来存储结果
	results := make([]map[string]interface{}, 0)

	// 处理每一行
	for rows.Next() {
		// 为每一列分配一个接口类型的切片
		values := make([]interface{}, len(columns))
		for i := range values {
			var value interface{}
			values[i] = &value
		}

		if err := rows.Scan(values...); err != nil {
			return nil, logError("scanning row failed", err)
		}

		// 将每一行的值与列名组合成一个 map
		result := make(map[string]interface{})
		for i, col := range columns {
			val := values[i].(*interface{})
			result[col] = ConvertValue(*val)
		}
		results = append(results, result)
	}

	// 检查迭代中的错误
	if err := rows.Err(); err != nil {
		return nil, logError("iterating rows failed", err)
	}

	return results, nil
}

// convertValue 处理各种可能的返回值，将它们转换为合理的类型
func ConvertValue(value interface{}) interface{} {
	switch v := value.(type) {
	case []byte:
		return string(v) // 字节数组转换为字符串
	case nil:
		return nil // 处理数据库中的 NULL 值
	default:
		return v // 其他类型保持原样
	}
}

// ExecuteNonQuery 执行非查询操作（插入、更新、删除），并记录日志
func ExecuteNonQuery(query string, args ...interface{}) (bool, error) {
	// 执行 SQL 查询
	result, err := db.Exec(query, args...)
	if err != nil {
		logError("non-query execution failed", err)
		return false, err // 返回 false 和错误
	}

	// 获取受影响的行数
	affectedRows, err := result.RowsAffected()
	if err != nil {
		logError("failed to get affected rows", err)
		return false, err // 返回 false 和错误
	}

	// 获取最后插入的行 ID
	lastInsertId, err := result.LastInsertId()
	if err != nil {
		logError("failed to get last insert ID", err)
		return false, err // 返回 false 和错误
	}

	// 打印日志
	log.Printf("SQL executed: %s, Affected Rows: %d, Last Insert ID: %d", query, affectedRows, lastInsertId)

	return true, nil // 返回 true 表示成功
}

// logError 封装错误日志记录
func logError(message string, err error) error {
	log.Printf("%s: %v", message, err)
	return err
}
